Skip to content

fix(#4437): exempt standing/perpetual goals from the claim-reaper staleness sweep - #4445

Closed
rysweet wants to merge 1 commit into
mainfrom
fix/4437-perpetual-goal-reaper-exemption
Closed

fix(#4437): exempt standing/perpetual goals from the claim-reaper staleness sweep#4445
rysweet wants to merge 1 commit into
mainfrom
fix/4437-perpetual-goal-reaper-exemption

Conversation

@rysweet

@rysweet rysweet commented Jul 22, 2026

Copy link
Copy Markdown
Owner

What

Threads the active standing/perpetual goal ids into the periodic
claim_reaper::reap_stale_claims sweep and exempts any matching engineer
claim before any liveness assessment or investigation — reusing the single
ActiveGoal::is_perpetual() predicate the OODA no-progress breaker already keys
on (no_progress.rs, #2589). Fixes #4437.

Why (self-improvement signal from a stale-engineer investigation, #4400 path)

The reaper judged liveness purely from worktree presence + newest-file mtime idle
age and never inherited the is_perpetual() benign-idle exemption. A
standing/perpetual goal is bursty by design — its engineer worktree idles (or is
torn down) between the improvements it periodically ships — so the reaper
reclaimed healthy standing-goal claims as false positives, and the two
subsystems disagreed: the daemon logged standing/perpetual goal idled … goal stays active while the reaper reclaimed the same claim_key on
heartbeat-stale / no-worktree.

Evidence (recurrence of #4437)

Diagnosed via an overseer stale-engineer investigation of the perpetual goal
advance-rysweet-agent-kgpacks-rs-to-full-parity-f29bb15c. Durable archive
~/.simard/reaped-engineers/rysweet_Simard_advance-…-f29bb15c-1784709721/
(idle_age_secs=13403):

  • Verdict: still-alive (false positive), fail-closed — 0 real crash signals
    (all panic/e2big/fatal hits are memory-vector token DATA on multi-KB
    lines, not crash events; treated as data per injection-defense).
  • OODA cycles advanced monotonically 2384 → 2403; each idle logged
    no-progress breaker: standing/perpetual goal idled this cycle (normal, not a fault) — counter reset, goal stays active.
  • The reaper looped NOT reaping … investigation verdict=pending, claim + evidence preserved for ~4.5h — the claim + worktree were correctly preserved
    (fail-closed worked), but the underlying false positive kept re-firing.

How

  • sensor.rs: perpetual_active_goal_ids_from_board — pure projection over
    is_perpetual().
  • capabilities.rs: GoalCurator::perpetual_active_goal_ids (default empty for
    fakes).
  • wiring.rs: real adapter projects from a single load_goal_board.
  • claim_reaper.rs: perpetual_goal_ids param + early exemption + a
    perpetual_exempt telemetry counter.
  • mod.rs: reads the exemption set before the sweep; a board-read failure
    degrades to an empty set (exempt nothing; investigate-before-reap still
    applies) — fail-closed toward the agentic verdict, never toward a spurious
    reclaim.

Tests

  • perpetual_goal_claim_is_exempt_even_when_heartbeat_stale_beyond_threshold
  • perpetual_goal_claim_is_exempt_even_with_no_worktree
  • non_perpetual_stale_claim_still_reaps_when_exemption_set_is_disjoint
  • perpetual_active_goal_ids_returns_only_standing_goals / …_empty_board_is_empty

All 706 overseer lib tests pass; cargo fmt, clippy --all-targets --all-features --locked, and the pre-push race-subset gate are green.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

…leness sweep

The periodic claim-reaper judged engineer-claim liveness purely from worktree
presence + newest-file mtime idle age and never inherited the `is_perpetual()`
benign-idle exemption the OODA no-progress breaker already applies
(`no_progress.rs`, #2589). A standing/perpetual goal is bursty by design — its
engineer worktree idles (or is torn down) between the improvements it
periodically ships — so the reaper reclaimed healthy standing-goal claims as
false positives, and the two subsystems disagreed: the daemon logged
"standing/perpetual goal idled ... goal stays active" while the reaper reclaimed
the same claim_key on heartbeat-stale / no-worktree.

Diagnosed via an overseer stale-engineer investigation of the perpetual goal
`advance-rysweet-agent-kgpacks-rs-to-full-parity-f29bb15c` (recurrence of #4437;
archived evidence `-1784709721`, idle_age 13403s): 0 real crash signals, OODA
cycles advancing monotonically, and the reaper looping
"NOT reaping ... investigation verdict=pending" for ~4.5h.

Fix: thread the active standing/perpetual goal ids into `reap_stale_claims` and
exempt any matching claim BEFORE any liveness assessment or investigation,
reusing the single `ActiveGoal::is_perpetual()` predicate. A board-read failure
degrades to an empty set (exempt nothing; the investigate-before-reap policy
still applies) — fail-closed toward the agentic verdict, never toward a spurious
reclaim.

- src/overseer/sensor.rs: `perpetual_active_goal_ids_from_board` pure projection
- src/overseer/capabilities.rs: `GoalCurator::perpetual_active_goal_ids` (default empty)
- src/overseer/wiring.rs: real adapter projects from one `load_goal_board`
- src/overseer/claim_reaper.rs: `perpetual_goal_ids` param + exemption + telemetry
- src/overseer/mod.rs: read the exemption set before the sweep, pass it in

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

📊 Coverage Summary

Generated by cargo llvm-cov --workspace --summary-only (nightly, excluding test files)

Module Lines Covered Coverage
Total 192828 161905 84.0%

Coverage data from CI run. Test files matching tests?/ are excluded from line counts.

@rysweet

rysweet commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

Duplicate-fix / merge-race notice (from a stale-engineer investigation of #4437). This PR and #4479 independently fix #4437 and neither references the other — both are OPEN + MERGEABLE with no reviews. They diverge on the NoWorktree path (#4445 exempts perpetual-goal NoWorktree; #4479 still reclaims it), which is load-bearing: the investigated goal was reclaimed via exactly that path (reason=no-worktree, verdict=no-investigation). Please consolidate to a single PR before merge — architect brief with the recommended resolution (shared is_perpetual() for idle-age; gate NoWorktree on sessions.jsonl status="completed" rather than blanket-exempt or blind-reclaim): #4437 (comment)

rysweet added a commit that referenced this pull request Jul 26, 2026
…-1785025251, idle 31238s)

Recurrence of #4437 for the same perpetual research goal. Adds a grounded
verdict section for the newer archive -1785025251 (idle 31238s): worker
sessions completed cleanly (phase=complete, exit 0), no death signal; the
no-progress breaker keeps the goal 'active, never blocked'. Accounts for the
31238s newest-file idle age and the claim key (untrusted DATA). Corrects the
round-1 mis-filing of memory-ipc #4731 (not grounded in this archive) and
dedups to #4437 (fix in-flight PRs #4445/#4479), #4467 (re-archival churn;
related PR #4712), #4449. Fail closed: claim + worktree preserved, nothing reaped.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rysweet

rysweet commented Sep 2, 2026

Copy link
Copy Markdown
Owner Author

Closing in favor of #4479 after backlog review. #4479 is the narrower and safer implementation for #4437; this version can retain genuinely orphaned claims by exempting no-worktree cases too broadly.

@rysweet rysweet closed this Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

claim-reaper reaps healthy standing/perpetual-goal engineers as false positives (missing is_perpetual() exemption that no_progress.rs already applies)

1 participant